home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / os / sprite / pdev.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-19  |  20.2 KB  |  759 lines

  1. /*-
  2.  * pdev.c --
  3.  *    Functions for handling a connection to a client over a pseudo-device.
  4.  *    Goal of these routine is to make a pdev connection look like a 
  5.  *    Unix domain socket.
  6.  *
  7.  *    For each client, we have two buffers -- a 2K output buffer, from
  8.  *    which the client reads, and a 2K request buffer, to which it writes.
  9.  *    The size for the output buffer is based on examination of the size
  10.  *    of buffers used in the old pseudo-device implementation. None
  11.  *    was larger than 2K, so... The input buffer size is based on the
  12.  *    size of Xlib's output buffer -- 2K. This is obviously inadequate for
  13.  *    large amounts of image data, but for most applications it should
  14.  *    be fine.
  15.  *
  16.  *
  17.  *
  18.  * Copyright (c) 1987 by the Regents of the University of California
  19.  *
  20.  * Permission to use, copy, modify, and distribute this
  21.  * software and its documentation for any purpose and without
  22.  * fee is hereby granted, provided that the above copyright
  23.  * notice appear in all copies.  The University of California
  24.  * makes no representations about the suitability of this
  25.  * software for any purpose.  It is provided "as is" without
  26.  * express or implied warranty.
  27.  *
  28.  *
  29.  */
  30. #ifndef lint
  31. static char rcsid[] =
  32. "$Header: /X11/R4/src/cmds/X/os/sprite/RCS/pdev.c,v 1.13 91/10/19 13:29:27 mendel Exp $ SPRITE (Berkeley)";
  33. #endif lint
  34.  
  35. #define NEED_REPLIES /* For Debugging Only */
  36.  
  37. #define DEBUG_PDEV    0
  38. #define    DBG_PRINT    ErrorF
  39.  
  40. #define    min(a,b)    (((a) < (b)) ? (a) : (b))
  41.  
  42. #include    <fs.h>
  43. #include    <stdlib.h>
  44. #include    <dev/pdev.h>
  45. #include    <errno.h>
  46. #include    <status.h>
  47. #include    <stdio.h>
  48. #include    <sys/time.h>
  49. #include <sys/types.h>
  50. #include <sys/uio.h>
  51.  
  52. #define OUT_BUF_SIZE        2048
  53. #define IN_BUF_SIZE        2048
  54.  
  55. /*
  56.  * The private data maintained for a pseudo-device client
  57.  */
  58. typedef struct {
  59.     int                  streamID;   /* Server stream over which we get the
  60.                      * buffer pointers */
  61.     int                  state;
  62. #define    PDEV_WRITE_STALL    0x0001    /* Stall on write request. */
  63. #define PDEV_REQ_EMPTY            0x0002    /* Request buffer is empty */
  64. #define PDEV_READ_EMPTY            0x0004     /* Read buffer is empty */
  65.  
  66.     /*
  67.      * Request (inBuf) and read-ahead (outBuf) buffers
  68.      */
  69.     char            outBuf[OUT_BUF_SIZE];
  70.     char              *outPtr;    /* Next place to store data */
  71.  
  72.     char              inBuf[IN_BUF_SIZE];
  73.     Pdev_Request    *reqPtr;    /* Address of next request to process */
  74.     char              *inPtr;        /* Position in current request */
  75.     int            inSize;        /* Amount of data valid in inBuf write 
  76.                      * request. */
  77.  
  78.     Pdev_BufPtrs      curPtrs;    /* Current pointers for the two buffers */
  79.  
  80. } PdevPrivRec, *PdevPrivPtr;
  81.  
  82. #define    MAX_FD    1024
  83. static PdevPrivPtr privRecPtrs[MAX_FD];
  84. static int PdevMaster = -2;
  85.  
  86. static void PdevSetPtrs();
  87. static void PdevRequestHandled();
  88.  
  89. /*-
  90.  *-----------------------------------------------------------------------
  91.  * PdevCreate --
  92.  *    Create a pseudo-device connection MASTER.
  93.  *
  94.  * Results:
  95.  *    Open Pdev file descriptor. -1 on error. (errno set)
  96.  *
  97.  * Side Effects:
  98.  *    The pseudo-device MASTER is created are opened.
  99.  *
  100.  *-----------------------------------------------------------------------
  101.  */
  102. int
  103. PdevCreate(pathName)
  104.     char    *pathName;    /* The pathname of PDEV */
  105. {
  106.     int              pdevConn;
  107.     ReturnStatus  status;
  108.  
  109.     /*
  110.      * Create the pseudo-device, 
  111.      */
  112.  
  113.     status = Fs_Open (pathName,
  114.         FS_NON_BLOCKING | FS_CREATE | FS_READ | FS_PDEV_MASTER,
  115.         0666, &pdevConn);
  116.     if (status != 0) {
  117.     errno = Compat_MapCode(status);
  118.     DBG_PRINT (pathName);
  119.     return -1;
  120.     }
  121.     PdevMaster = pdevConn;
  122.     return pdevConn;
  123. }
  124.  
  125. /*-
  126.  *-----------------------------------------------------------------------
  127.  * PdevAccept --
  128.  *    Accept connections from new clients. 
  129.  *
  130.  * Results:
  131.  *    Stream ID of new connection -1 if error.
  132.  *
  133.  * Side Effects:
  134.  *    Memory is allocated.
  135.  *
  136.  *-----------------------------------------------------------------------
  137.  */
  138. int
  139. PdevAccept (pdevDev)
  140.     int            pdevDev;    /* Pdev master. */
  141. {
  142.     Pdev_Notify          note;            /* Notification of new stream */
  143.     PdevPrivPtr        pdevPriv;       /* New private information for us */
  144.     Pdev_Request    *pdevReq;       /* Pointer to current request */
  145.     Pdev_Reply     openReply;          /* Reply to open request */
  146.     Pdev_SetBufArgs    bufArgs;        /* Structure to set r/w buffers */
  147.     int                  numBytes;       /* Number of bytes read */
  148.     Boolean           writeBehind;    /* For IOC_PDEV_WRITE_BEHIND */
  149.     Pdev_BufPtrs      bufPtrs;    /* New buffer pointers for stream */
  150.  
  151.     writeBehind = TRUE;            /* Turn on write-behind */
  152.  
  153.     /*
  154.      * Read the connection request. 
  155.      */
  156.     numBytes = read(pdevDev, (char *) ¬e, sizeof(note));
  157.     if ((numBytes != sizeof(note)) || (note.magic != PDEV_NOTIFY_MAGIC)) {
  158.     return -1;
  159.     }
  160.     /*
  161.      * If streamID is too large ignore connection.
  162.      */
  163.     if (note.newStreamID >= MAX_FD) {
  164.     (void) close(note.newStreamID);
  165.     return -1;
  166.     }
  167.  
  168.     /*
  169.      * Allocate some memory for the private data of request.
  170.      */
  171.     pdevPriv = (PdevPrivPtr) malloc(sizeof(PdevPrivRec));
  172.     pdevPriv->streamID =                     note.newStreamID;
  173.     pdevPriv->state =                       PDEV_REQ_EMPTY|PDEV_READ_EMPTY;
  174.     pdevPriv->curPtrs.magic =               PDEV_BUF_PTR_MAGIC;
  175.     pdevPriv->curPtrs.requestFirstByte =    -1;
  176.     pdevPriv->curPtrs.requestLastByte =     -1;
  177.     pdevPriv->curPtrs.readFirstByte =       -1;
  178.     pdevPriv->curPtrs.readLastByte =        -1;
  179.     pdevPriv->inPtr =                       (char *)NULL;
  180.     pdevPriv->inSize =                       0;
  181.     pdevPriv->outPtr =                      pdevPriv->outBuf;
  182.  
  183.     bufArgs.requestBufAddr = pdevPriv->inBuf;
  184.     bufArgs.requestBufSize = IN_BUF_SIZE;
  185.     bufArgs.readBufAddr = pdevPriv->outBuf;
  186.     bufArgs.readBufSize = OUT_BUF_SIZE;
  187.  
  188.     (void)Fs_IOControl(pdevPriv->streamID, IOC_PDEV_SET_BUF,
  189.                sizeof(bufArgs), (Address)&bufArgs,
  190.                0, (Address)NULL);
  191.     (void)Fs_IOControl(pdevPriv->streamID, IOC_PDEV_WRITE_BEHIND,
  192.                sizeof(Boolean), (Address) &writeBehind,
  193.                0, (Address)NULL);
  194.     /*
  195.      * Wait for open request to come in from client.
  196.      */
  197.     numBytes = read(pdevPriv->streamID, (char *) &bufPtrs, sizeof(bufPtrs));
  198.     if (numBytes == -1) {
  199.     if (DEBUG_PDEV) {
  200.         DBG_PRINT ("PdevWaitForReadable");
  201.     }
  202.     free((char *) pdevPriv);
  203.     return (-1);
  204.     }
  205.     if (bufPtrs.magic != PDEV_BUF_PTR_MAGIC) {
  206.     if (DEBUG_PDEV) {
  207.         DBG_PRINT ("Buffer magic numbers don't match\n");
  208.     }
  209.     free((char *) pdevPriv);
  210.     return (-1);
  211.     }
  212.     PdevSetPtrs(pdevPriv, &bufPtrs);
  213.     if (pdevPriv->reqPtr->hdr.operation == PDEV_OPEN) {
  214.     pdevReq = pdevPriv->reqPtr;
  215.  
  216.     openReply.magic =       PDEV_REPLY_MAGIC;
  217.     openReply.selectBits =     FS_WRITABLE | FS_READABLE;
  218.     openReply.replySize =    0;
  219.     openReply.replyBuf =    (Address)NULL;
  220.     openReply.signal = 0;
  221.     openReply.code = 0;
  222.  
  223.     openReply.status = SUCCESS;
  224.     (void) Fs_IOControl(pdevPriv->streamID, IOC_PDEV_REPLY,
  225.                 sizeof(openReply), (Address)&openReply,
  226.                 0, (Address)NULL);
  227.     }
  228.  
  229.     PdevRequestHandled(pdevPriv);
  230.     /*
  231.      * Mark stream as non-blocking and save private data away.
  232.      */
  233.     Ioc_SetBits(pdevPriv->streamID, IOC_NON_BLOCKING); 
  234.     privRecPtrs[pdevPriv->streamID] = pdevPriv;
  235.     return pdevPriv->streamID;
  236. }
  237.     
  238. /*-
  239.  *-----------------------------------------------------------------------
  240.  * PdevClose --
  241.  *    Close down a connection.
  242.  *    XXX: Maybe we should wait for the read-ahead buffer to drain?
  243.  *
  244.  * Results:
  245.  *    -1 if error. 0 if success. errno set.
  246.  *
  247.  * Side Effects:
  248.  *    The pseudo-device stream is closed and the private data freed
  249.  *    The stream is removed from these masks:
  250.  *        AllStreamsMask, SavedAllStreamsMask, AllClientsMask,
  251.  *        SavedAllClientsMask, ClientsWithInputMask
  252.  *
  253.  *-----------------------------------------------------------------------
  254.  */
  255. int
  256. PdevClose (pdev)
  257.     int pdev;
  258. {
  259.     register PdevPrivPtr pdevPriv;
  260.  
  261.     if ((pdev < 0) || (pdev >= MAX_FD)) {
  262.     errno = EINVAL;
  263.     return -1;
  264.     }
  265.     pdevPriv = privRecPtrs[pdev];
  266.     if (pdevPriv == (PdevPrivPtr) NULL) {
  267.     errno = EINVAL;
  268.     return -1;
  269.     }
  270.  
  271.     privRecPtrs[pdev] = (PdevPrivPtr) NULL;
  272.     free((char *) pdevPriv);
  273.  
  274.     return close(pdev);
  275. }
  276.  
  277.  
  278.  
  279. /*-
  280.  *-----------------------------------------------------------------------
  281.  * PdevRead --
  282.  *    Return bytes from the given client. 
  283.  *
  284.  * Results:
  285.  *    Number of bytes read. -1 if error and errno set.
  286.  *
  287.  * Side Effects:
  288.  *
  289.  *-----------------------------------------------------------------------
  290.  */
  291. /*ARGSUSED*/
  292. int
  293. PdevRead (pdev, bufferPtr, bufLen)
  294.     int            pdev;
  295.     char        *bufferPtr;
  296.     int            bufLen;
  297. {
  298.     PdevPrivPtr      pdevPriv;   /* Private data for the client */
  299.     int                  need;        /* Number of bytes needed for the
  300.                      * current request */
  301.     Pdev_BufPtrs      bufPtrs;    /* New pointers for buffer */
  302.     int                  numBytes;
  303.     Pdev_ReplyData     reply;
  304.  
  305.     if ((pdev < 0) || (pdev >= MAX_FD)) {
  306.     errno = EINVAL;
  307.     return -1;
  308.     }
  309.     pdevPriv = privRecPtrs[pdev];
  310.     if (pdevPriv == (PdevPrivPtr) NULL) {
  311.     errno = EINVAL;
  312.     return -1;
  313.     }
  314.     numBytes = 0;
  315.     /*
  316.      * Use any data waiting from the last WRITE request. 
  317.      */
  318.     if (pdevPriv->inSize > 0) {
  319.     numBytes = min(pdevPriv->inSize, bufLen);
  320.     bcopy(pdevPriv->inPtr, bufferPtr, numBytes);
  321.     bufLen -= numBytes;
  322.     pdevPriv->inSize -= numBytes;
  323.     if (pdevPriv->inSize == 0) {
  324.         PdevRequestHandled(pdevPriv);
  325.     }
  326.     }
  327.     if (bufLen == 0) {
  328.     return numBytes;
  329.     }
  330.     if (pdevPriv->state & PDEV_REQ_EMPTY) {
  331.     int count;
  332.     /*
  333.      * If the request buffer is empty, we think, then we need to see if
  334.      * the kernel has anything for us. 
  335.      */
  336.     count = read(pdev, &bufPtrs, sizeof(bufPtrs));
  337.     if (count == -1) {
  338.         if (errno != EWOULDBLOCK) {
  339.         if (DEBUG_PDEV) {
  340.             DBG_PRINT ("Reading buffer pointers");
  341.         }
  342.         return(-1);
  343.         } 
  344.     } else if ((count != sizeof(bufPtrs)) ||
  345.         (bufPtrs.magic != PDEV_BUF_PTR_MAGIC)) {
  346.         if (DEBUG_PDEV) {
  347.             DBG_PRINT ("Improper data when reading buffer pointers");
  348.         }
  349.         return (-1);
  350.     } else {
  351.         PdevSetPtrs(pdevPriv, &bufPtrs);
  352.     }
  353.     }
  354.  
  355.     /*
  356.      * Process the requests until we run out or get enought data.
  357.      */
  358.     while (!(pdevPriv->state & PDEV_REQ_EMPTY) && (bufLen > 0)) {
  359.     switch (pdevPriv->reqPtr->hdr.operation) {
  360.         case PDEV_WRITE_ASYNC:
  361.         case PDEV_WRITE: {
  362.         int got;
  363.         if (DEBUG_PDEV) {
  364.             DBG_PRINT ("pdev %d: PDEV_WRITE(%d)\n",
  365.                pdev,
  366.                pdevPriv->reqPtr->hdr.requestSize);
  367.         }
  368.         pdevPriv->inPtr = (char *)&pdevPriv->reqPtr[1];
  369.         pdevPriv->inSize = pdevPriv->reqPtr->hdr.requestSize;
  370.         got = min(bufLen, pdevPriv->inSize);
  371.         bcopy(pdevPriv->inPtr, bufferPtr + numBytes, got);
  372.         bufLen -= got;
  373.         pdevPriv->inSize -= got;
  374.         pdevPriv->inPtr += got;
  375.         numBytes += got;
  376.         if (pdevPriv->inSize == 0) { 
  377.             PdevRequestHandled(pdevPriv);
  378.         }
  379.         break;
  380.         }
  381.         case PDEV_CLOSE:
  382.         /*
  383.          * We like closes. We just return -1 to cause the
  384.          * connection to be aborted.
  385.          */
  386.         if (DEBUG_PDEV) {
  387.             DBG_PRINT ("client %d: PDEV_CLOSE\n", pdevPriv->streamID);
  388.         }
  389.         reply.magic = PDEV_REPLY_MAGIC;
  390.         reply.status = SUCCESS;
  391.         reply.selectBits = 0;
  392.         reply.replySize = 0;
  393.         reply.replyBuf = (Address)NULL;
  394.         reply.signal = 0;
  395.         reply.code = 0;
  396.         (void)Fs_IOControl(pdevPriv->streamID,
  397.                    IOC_PDEV_REPLY,
  398.                    sizeof(reply), (Address)&reply,
  399.                    0, (Address)NULL);
  400.         PdevRequestHandled(pdevPriv);
  401.         errno = ECONNRESET;
  402.         return (-1);
  403.         case PDEV_IOCTL: {
  404.         /*
  405.          * All this should be unnecessary, but we reply to it
  406.          * anyway and pretend we know what we're doing when it
  407.          * comes to the IOC_NUM_READABLE
  408.          */
  409.         char    *inBuffer;
  410.         int    replyBuf;
  411.         int    command;
  412.         
  413.         reply.magic = PDEV_REPLY_MAGIC;
  414.         reply.status = SUCCESS;
  415.         reply.selectBits =
  416.             ((pdevPriv->state & PDEV_READ_EMPTY)?0:FS_READABLE) |
  417.             FS_WRITABLE;
  418.         reply.replySize = 0;
  419.         reply.replyBuf = (Address)&replyBuf;
  420.         
  421.         if (pdevPriv->reqPtr->hdr.requestSize) {
  422.             inBuffer = (char *)&pdevPriv->reqPtr[1];
  423.         } else {
  424.             inBuffer = (char *)NULL;
  425.         }
  426.         if (DEBUG_PDEV) {
  427.             DBG_PRINT ("pdev %d: PDEV_IOCTL(%x, %d, %x, %d, ...)\n",
  428.                pdevPriv->streamID,
  429.                pdevPriv->reqPtr->param.ioctl.command,
  430.                pdevPriv->reqPtr->hdr.requestSize,
  431.                inBuffer,
  432.                pdevPriv->reqPtr->hdr.replySize);
  433.         }
  434.         
  435.         switch (pdevPriv->reqPtr->param.ioctl.command) {
  436.             case IOC_NUM_READABLE:
  437.             /*
  438.              * XXX: This is already handled by the
  439.              * kernel since it knows how much it has
  440.              * more accurately than I do.
  441.              */
  442.             reply.replySize = sizeof(int);
  443.             replyBuf = pdevPriv->curPtrs.readLastByte -
  444.                 pdevPriv->curPtrs.readFirstByte;
  445.             break;
  446.             case IOC_SET_BITS:
  447.             case IOC_SET_FLAGS:
  448.             break;
  449.             case IOC_CLEAR_BITS:
  450.             case IOC_GET_FLAGS:
  451.             replyBuf = 0;
  452.             reply.replySize = sizeof(int);
  453.             break;
  454.             default:
  455.             if (DEBUG_PDEV) {
  456.                 DBG_PRINT ("Invalid IOCTL %x\n",
  457.                    pdevPriv->reqPtr->param.ioctl.command);
  458.             }
  459.             reply.status = FS_DEVICE_OP_INVALID;
  460.             break;
  461.         }
  462.         reply.signal = 0;
  463.         reply.code = 0;
  464.         if (reply.replySize > 0) {
  465.             *(int *)reply.data = replyBuf;
  466.             command = IOC_PDEV_SMALL_REPLY;
  467.         } else {
  468.             command = IOC_PDEV_REPLY;
  469.         }
  470.         (void)Fs_IOControl(pdevPriv->streamID,
  471.                    command,
  472.                    sizeof(reply), (Address)&reply,
  473.                    0, (Address)NULL);
  474.         PdevRequestHandled(pdevPriv);
  475.         break;
  476.         }
  477.         default:
  478.         /*
  479.          * Bad pseudo-device request -- close the beastie down
  480.          */
  481.         reply.magic = PDEV_REPLY_MAGIC;
  482.         reply.status = FS_DEVICE_OP_INVALID;
  483.         reply.selectBits = 0;
  484.         reply.replySize = 0;
  485.         reply.replyBuf = (Address)NULL;
  486.         reply.signal = 0;
  487.         reply.code = 0;
  488.         if (DEBUG_PDEV) {
  489.             DBG_PRINT ("Bad new pdev request %d pdev %d\n",
  490.                pdevPriv->reqPtr->hdr.operation,
  491.                pdevPriv->streamID);
  492.         }
  493.         (void)Fs_IOControl(pdevPriv->streamID,
  494.                    IOC_PDEV_REPLY,
  495.                    sizeof(reply), (Address)&reply,
  496.                    0, (Address)NULL);
  497.         PdevRequestHandled(pdevPriv);
  498.         errno = ECONNRESET;
  499.         return (-1);
  500.     }
  501.     }
  502.     if (numBytes == 0) {
  503.     errno = EWOULDBLOCK;
  504.     return (-1);
  505.     }
  506.     return numBytes;
  507. }
  508.  
  509. /*-
  510.  *-----------------------------------------------------------------------
  511.  * PdevWritev --
  512.  *    Write data to the client. Data are copied into the read buffer
  513.  *    as much as possible. 
  514.  *
  515.  * Results:
  516.  *    Number of bytes written.
  517.  *
  518.  * Side Effects:
  519.  *    The data bytes are stuffed into the buffer for the client, awaiting
  520.  *    a read request from the client.
  521.  *
  522.  *-----------------------------------------------------------------------
  523.  */
  524. int
  525. PdevWritev(pdev, iov, iovcnt)
  526.     int        pdev;
  527.     struct iovec *iov;
  528.     int iovcnt;
  529. {
  530.     register PdevPrivPtr    pdevPriv;        /* Data private to client */
  531.     ReturnStatus        status;
  532.     int       numWrite, numWritten, i;
  533.  
  534.  
  535.     if ((pdev < 0) || (pdev >= MAX_FD)) {
  536.     errno = EINVAL;
  537.     return -1;
  538.     }
  539.     pdevPriv = privRecPtrs[pdev];
  540.     if (pdevPriv == (PdevPrivPtr) NULL) {
  541.     errno = EINVAL;
  542.     return -1;
  543.     }
  544.  
  545.     if (pdevPriv->curPtrs.readLastByte >= (OUT_BUF_SIZE - 1)) {
  546.     pdevPriv->state |= PDEV_WRITE_STALL;
  547.     errno = EWOULDBLOCK;
  548.     return -1;
  549.     }
  550.     pdevPriv->state &= ~PDEV_WRITE_STALL;
  551.  
  552.     numWritten = 0;
  553.     for (i = 0; (i < iovcnt) && 
  554.         (pdevPriv->curPtrs.readLastByte < (OUT_BUF_SIZE - 1)); i++) {
  555.     int spaceAvailable;
  556.  
  557.     spaceAvailable = (pdevPriv->curPtrs.readLastByte == -1) ? OUT_BUF_SIZE 
  558.                 : (OUT_BUF_SIZE - pdevPriv->curPtrs.readLastByte);
  559.  
  560.     numWrite = min(iov[i].iov_len, spaceAvailable);
  561.     bcopy((char *) iov[i].iov_base, (char *) pdevPriv->outPtr, numWrite);
  562.  
  563.     /*
  564.      * Update the output pointers. Note that since readLastByte starts
  565.      * at -1, adding numWrite will point to the last valid byte of data
  566.      * in the buffer...
  567.      */
  568.     pdevPriv->curPtrs.readLastByte += numWrite;
  569.     pdevPriv->outPtr += numWrite;
  570.     numWritten += numWrite;
  571.     }
  572.  
  573.  
  574.     /*
  575.      * Inform kernel of new read buffer extents
  576.      */
  577.     status = Fs_IOControl(pdevPriv->streamID, IOC_PDEV_SET_PTRS,
  578.         sizeof(pdevPriv->curPtrs), (Address) &pdevPriv->curPtrs,
  579.         0, (Address) NULL);
  580.     if (status != 0) {
  581.     errno = Compat_MapCode(status);
  582.     if (DEBUG_PDEV) {
  583.         DBG_PRINT ("WriteClient: SET_PTRS");
  584.     }
  585.     return -1;
  586.     }
  587.     return (numWritten);
  588. }
  589.  
  590. /*-
  591.  *-----------------------------------------------------------------------
  592.  * PdevWrite --
  593.  *    Write data to the client. Data are copied into the read buffer
  594.  *    as much as possible. 
  595.  *
  596.  * Results:
  597.  *    Number of bytes written.
  598.  *
  599.  * Side Effects:
  600.  *    The data bytes are stuffed into the buffer for the client, awaiting
  601.  *    a read request from the client.
  602.  *
  603.  *-----------------------------------------------------------------------
  604.  */
  605. int
  606. PdevWrite(pdev, buf, nbytes)
  607.     int        pdev;
  608.     char *buf;
  609.     int    nbytes;
  610. {
  611.     struct iovec io;
  612.     io.iov_base = buf;
  613.     io.iov_len = nbytes;
  614.     return PdevWritev(pdev, &io, 1);
  615. }
  616.  
  617. int 
  618. PdevIsMaster(pdev)
  619.     int    pdev;
  620. {
  621.     return (pdev == PdevMaster);
  622. }
  623. int
  624. PdevIsPdevConn(pdev) 
  625. {
  626.     return ((pdev >= 0) && (pdev <= MAX_FD) && privRecPtrs[pdev]);
  627. }
  628.  
  629. /*-
  630.  *-----------------------------------------------------------------------
  631.  * PdevSetPtrs --
  632.  *    Set our idea of the state of the two buffers. Called when a
  633.  *    Pdev_BufPtrs structure is read from the kernel. If the read-ahead
  634.  *    buffer has been emptied by the kernel and there's overflow waiting
  635.  *    to go, copy it down and inform the kernel of it.
  636.  *
  637.  * Results:
  638.  *    None.
  639.  *
  640.  * Side Effects:
  641.  *    curPtrs is altered.
  642.  *
  643.  *-----------------------------------------------------------------------
  644.  */
  645. static void
  646. PdevSetPtrs(pdevPriv, bufPtrs)
  647.     PdevPrivPtr    pdevPriv;
  648.     Pdev_BufPtrs      *bufPtrs;
  649. {
  650.     if (DEBUG_PDEV) {
  651.     DBG_PRINT ("SetPtrs(%d): req %d:%d read %d:%d\n",
  652.            pdevPriv->streamID,
  653.            bufPtrs->requestFirstByte,
  654.            bufPtrs->requestLastByte,
  655.            bufPtrs->readFirstByte,
  656.            bufPtrs->readLastByte);
  657.     }
  658.  
  659.     /*
  660.      * First update the extent of the request buffer.
  661.      */
  662.     pdevPriv->curPtrs.requestLastByte = bufPtrs->requestLastByte;
  663.     if ((bufPtrs->requestLastByte != -1)  &&
  664.     (pdevPriv->state & PDEV_REQ_EMPTY)) {
  665.         /*
  666.          * We only pay attention to the requestFirstByte if going from
  667.          * an empty to a non-empty buffer, since we think we know where
  668.          * the first request byte actually is.
  669.          */
  670.         pdevPriv->curPtrs.requestFirstByte = bufPtrs->requestFirstByte;
  671.         pdevPriv->reqPtr =
  672.         (Pdev_Request *)&pdevPriv->inBuf[bufPtrs->requestFirstByte];
  673.         pdevPriv->inSize = 0;
  674.         pdevPriv->state &= ~PDEV_REQ_EMPTY;
  675.     }
  676.  
  677.     /*
  678.      * Then the extent of the read buffer.
  679.      */
  680.     pdevPriv->curPtrs.readFirstByte = bufPtrs->readFirstByte;
  681.     if (bufPtrs->readFirstByte == -1) {
  682.     int   numBytes;
  683.  
  684.     pdevPriv->state |= PDEV_READ_EMPTY;
  685.     pdevPriv->outPtr = pdevPriv->outBuf;
  686.  
  687.     /*
  688.      * Need to make this -1 so PdevWriteClient works correctly
  689.      * (it adds the number of bytes written to readLastByte without
  690.      * checking its value)
  691.      */
  692.     pdevPriv->curPtrs.readLastByte = -1;
  693.     }
  694. /*
  695.  * This is needed until select() on a pdev returns when it is writable.
  696.  */
  697.     if ((pdevPriv->state & PDEV_WRITE_STALL) && 
  698.     (pdevPriv->curPtrs.readLastByte < (OUT_BUF_SIZE - 1))) {
  699.     PdevClearWriteBlockHack(pdevPriv->streamID);
  700.     }
  701. }
  702.     
  703. /*-
  704.  *-----------------------------------------------------------------------
  705.  * PdevRequestHandled --
  706.  *    Tell the kernel that we have handled the request at
  707.  *    pdevPriv->reqPtr and update our own idea of the request buffer.
  708.  *
  709.  * Results:
  710.  *    None.
  711.  *
  712.  * Side Effects:
  713.  *    curPtrs.requestFirstByte is altered, inPtr is NULLed, the
  714.  *    PDEV_REQ_EMPTY flag will be set if the buffer is now empty.
  715.  *
  716.  *-----------------------------------------------------------------------
  717.  */
  718. static void
  719. PdevRequestHandled(pdevPriv)
  720.     PdevPrivPtr    pdevPriv;
  721. {
  722.     ReturnStatus status;
  723.  
  724.     pdevPriv->inPtr = (char *)NULL;
  725.     pdevPriv->inSize = 0;
  726.     pdevPriv->curPtrs.requestFirstByte += pdevPriv->reqPtr->hdr.messageSize;
  727.     pdevPriv->reqPtr =
  728.     (Pdev_Request *)&pdevPriv->inBuf[pdevPriv->curPtrs.requestFirstByte];
  729.  
  730.     if (pdevPriv->curPtrs.requestFirstByte >
  731.     pdevPriv->curPtrs.requestLastByte) {
  732.         pdevPriv->state |= PDEV_REQ_EMPTY;
  733.     }
  734.  
  735.     if (DEBUG_PDEV) {
  736.     DBG_PRINT ("RequestHandled(%d): req %d:%d read %d:%d\n",
  737.            pdevPriv->streamID, 
  738.            pdevPriv->curPtrs.requestFirstByte,
  739.            pdevPriv->curPtrs.requestLastByte,
  740.            pdevPriv->curPtrs.readFirstByte,
  741.            pdevPriv->curPtrs.readLastByte);
  742.     }
  743.  
  744.     status = Fs_IOControl(pdevPriv->streamID, IOC_PDEV_SET_PTRS,
  745.         sizeof(pdevPriv->curPtrs), (Address) &pdevPriv->curPtrs,
  746.         0, (Address) NULL);
  747.     if (status != 0) {
  748.     errno = Compat_MapCode(status);
  749.     if (DEBUG_PDEV) {
  750.         DBG_PRINT ("RequestHandled: SET_PTRS");
  751.     }
  752.     }
  753.     if (pdevPriv->state & PDEV_REQ_EMPTY) {
  754.     pdevPriv->curPtrs.requestFirstByte =
  755.         pdevPriv->curPtrs.requestLastByte = -1;
  756.     }
  757. }
  758.  
  759.